package base;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;

import utils.FileUtils;
import utils.IOUtils;
import utils.LogUtils;
import utils.UIUtils;

import bean.HomeBean;

import com.google.gson.Gson;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.RequestParams;
import com.lidroid.xutils.http.ResponseStream;
import com.lidroid.xutils.http.client.HttpRequest.HttpMethod;

import conf.constants;
import conf.constants.URLS;

/**
 * 网络连接的基类
 * 
 * @author Anson-pc
 * 
 * @param <T>
 */

public abstract class BaseProtocol<T> {
	
	public T loadData(int index) throws Exception {
		/**
		 * 从内存中加载
		 */
		T t = getDataFromMeory(index);
		if (t!= null) {
			Map<String, String> extraParams = getExtraParams();
			if (extraParams != null) {
				LogUtils.s("###从内存加载数据--》"+extraParams.get("packageName"));
				
			}else{
				LogUtils.s("###从内存加载数据--》"+getInterceKey()+"."+index);
			}
			return t;
		}
		
		
		//返回null,没有缓存或者缓存过期
		t = getDataFromLocal(index);
		if (t  != null) {
			//
			LogUtils.s("###从本地加载数据--》"+getCacehFile(index).getAbsolutePath());
			return t;
		}
		
		return getDataFromNet(index);
	}

	/**
	 * 从内存中加载数据
	 * @return
	 */
	private T getDataFromMeory(int index) {
		//表示内存有数据，直接从内存中获取
		BaseApplication app = (BaseApplication) UIUtils.getContext();
		Map<String,String> cacheMap = app.getCacheMap();
		/*-----------  添加详情的缓存页面 ----------*/
		Map<String, String> extraParams = getExtraParams();
		String key;
		if (extraParams != null) {
			key = getInterceKey()+"."+extraParams.get("packageName");
		}else{
			key = getInterceKey()+"."+index;
		}
		/*--------- end ----------*/
		
		String cacheJsonString = cacheMap.get(key);
		
		return  parseJsonString(cacheJsonString);
	}

	/**
	 * 从本地加载数据
	 * @param index
	 * @return
	 */
	private T getDataFromLocal(int index) {
		//数据保存在本地文件，直接解析本地文件的数据
		try {
			File cacheFile = getCacehFile(index);
			
			if (cacheFile.exists()) {
				BufferedReader reader = null;
				
				try {
					//读取文件的插入时间
					//判断是否过期
					reader = new BufferedReader(new FileReader(cacheFile));
					//读取第一行
					String insertTimeStr = reader.readLine();
					long insertTime = Long.parseLong(insertTimeStr);
					//判断是否过期，在常量文件定义一个过期时间，五分钟
					if (System.currentTimeMillis() - insertTime < constants.PROTOCOLTIMEOUT) {
						//读取有效的缓存
						String cacheJsonString = reader.readLine();
						/*-----------  缓存协议到内存中 ----------*/
						Map<String, String> extraParams = getExtraParams();
						BaseApplication  app = (BaseApplication) UIUtils.getContext();
						Map<String, String> cacheMap = app.getCacheMap();
						String key= "";
						if (extraParams!= null) {
							key = getInterceKey()+"."+extraParams.get("packageName");
						}else{
							key = getInterceKey()+"."+index;
						}
						
						cacheMap.put(key,cacheJsonString);
						/*--------- end ----------*/
						T t = parseJsonString(cacheJsonString);
						return t;
					}
				} finally  {
					IOUtils.close(reader);
				}
			}
		}  catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
		
	}

	/**
	 * 获取文件的保存路径
	 * @param index
	 * @return
	 */
	private File getCacehFile(int index) {
		/**
		 * 外置SD卡的目录，文件保存的路径
		 */
		String dir = FileUtils.getDir("json");
		//文件名需要保证唯一索引性
		/*-----------  添加详情的缓存页面 ----------*/
		Map<String, String> extraParams = getExtraParams();
		String fileName;
		if (extraParams != null) {
			fileName = getInterceKey()+"."+extraParams.get("packageName");
		}else{
			fileName = getInterceKey()+"."+index;
		}
		/*--------- end ----------*/
		
		File cacheFile = new File(dir,fileName);
		return cacheFile;
	}

	/**
	 * 从网络加载数据
	 * @param index
	 * @return
	 * @throws HttpException
	 * @throws IOException
	 */
	private T getDataFromNet(int index) throws HttpException, IOException {
		HttpUtils httpUtils = new HttpUtils();
		String url = URLS.BaseUrl + getInterceKey();

		// 请求的参数
		RequestParams params = new RequestParams();
		
		
		//由于详情页面的接口不一致，所以要重新定义一个方法
		Map<String,String> extraParams = getExtraParams();
		if (extraParams != null) {
			//遍历集合，取出元素
			for (Map.Entry<String, String> info : extraParams.entrySet()) {
				String key = info.getKey();
				String value = info.getValue();
				params.addQueryStringParameter(key, value);
			}
		}else{
			params.addQueryStringParameter("index", index+"");
		}
		
		
		ResponseStream responseStream = httpUtils.sendSync(HttpMethod.GET, url,
				params);

		String jsonString = responseStream.readString();
System.out.println("HomeFragment: " + jsonString);
		/*-----------  缓存协议到内存中 ----------*/
		BaseApplication  app = (BaseApplication) UIUtils.getContext();
		Map<String, String> cacheMap = app.getCacheMap();
		String key= "";
		if (extraParams!= null) {
			key = getInterceKey()+"."+extraParams.get("packageName");
		}else{
			key = getInterceKey()+"."+index;
		}
		
		cacheMap.put(key,jsonString);
		
		/*-----------  缓存协议内容到file中 ----------*/
		
			File cacheFile = getCacehFile(index);
			
			BufferedWriter writer = null;
			try {
			writer = new BufferedWriter(new FileWriter(cacheFile));
			
			//写入第一行
			writer.write(System.currentTimeMillis()+"");
			
			//换行
			writer.newLine();
			
			//写入协议的具体内容
			writer.write(jsonString);
		} finally {
			IOUtils.close(writer);
		}
		
		/*-----------  解析json数据 ----------*/

		// 解析json数据
		T t = parseJsonString(jsonString);

		return t;
	}

	/**
	 * 传递额外的参数,子类可以复写该方法传递额外的参数
	 * @return
	 */
	protected Map<String, String> getExtraParams() {
		return null;
	}

	/**
	 * 具体的json解析过程
	 * 
	 * @param jsonString
	 * @return
	 */
	protected  T parseJsonString(String jsonString){
		Gson gson = new Gson();
		//字节码对象
		ParameterizedType genericSuperclass = (ParameterizedType) this.getClass().getGenericSuperclass();
		Type[] actualTypeArguments = genericSuperclass.getActualTypeArguments();
		Type type = actualTypeArguments[0];
		
		return gson.fromJson(jsonString,type);
	}

	/**
	 * 返回协议的关键字 必须实现但是不知道具体实现
	 * 
	 * @call
	 * @return
	 */
	protected abstract String getInterceKey();
}
